/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package jplurk.api.util;

import org.apache.log4j.Logger;

/**
 *
 * @author Jose
 */
public class BaseConvert {

    public static Logger logger = Logger.getLogger(BaseConvert.class);
    
    public static Long toDecimal(String value, Integer base) throws IllegalArgumentException {
        
        if (base < 2 || base > 36) {
            throw new IllegalArgumentException("Base must be in range 2-36");
        }
        
        // Get the valid digits for this base
        String digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".substring(0, base);
        logger.debug("Base: " + base + " - valid digits: " + digits);
        
        String valueStr = value.toUpperCase();
        Integer valueLength = valueStr.length();
        Long decimalValue = new Long(0);
        for ( int i = 0; i < valueLength ; i++) {
            
            // Get the value of the digit at position i
            Long digitValue = new Long(digits.indexOf(valueStr.charAt(i)));
            
            // If the digit is not found, then throw an error
            if (digitValue < 0) {
                throw new IllegalArgumentException("Invalid value specified for base: " + base);
            }
            
            // Add to the decimal value
            decimalValue += digitValue * new Long(Math.round(Math.pow(base, (valueLength - i - 1))));
        }

        return decimalValue;
    }
    
    public static String fromDecimal(Long value, Integer base) throws IllegalArgumentException {
        
        if (base < 2 || base > 36) {
            throw new IllegalArgumentException("Base must be in range 2-36");
        }
        
        // Get the valid digits for this base
        String digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".substring(0, base);
        logger.debug("Base: " + base + " - valid digits: " + digits);
        
        Long remainder;
        Long quotient = value;
        String result = "";
        char digit;
        
        do {
            remainder = quotient % base;
            quotient /= base;
            digit = digits.charAt(remainder.intValue());
            result = digit + result; 
        } while (quotient != 0);
        
        return result;
    }
    
    public static void main(String[] args) {
        
        logger.info("Base 2 to decimal: 1001 = " + BaseConvert.toDecimal("1001", 2));
        logger.info("Base 2 to decimal: 001 = " + BaseConvert.toDecimal("001", 2));
        logger.info("Base 2 to decimal: 10 = " + BaseConvert.toDecimal("10", 2));
        logger.info("Base 2 to decimal: 1 = " + BaseConvert.toDecimal("1", 2));
        logger.info("Decimal to base 2: 9 = " + BaseConvert.fromDecimal(new Long(9), 2));
        logger.info("Decimal to base 2: 1 = " + BaseConvert.fromDecimal(new Long(1), 2));
        logger.info("Decimal to base 2: 53 = " + BaseConvert.fromDecimal(new Long(53), 2));
        
        logger.info("Base 16 to decimal: F = " + BaseConvert.toDecimal("F", 16));
        logger.info("Base 16 to decimal: 11 = " + BaseConvert.toDecimal("11", 16));
        logger.info("Base 16 to decimal: A1 = " + BaseConvert.toDecimal("A1", 16));
        logger.info("Base 16 to decimal: 054C = " + BaseConvert.toDecimal("054C", 16));
        logger.info("Decimal to base 16: 53 = " + BaseConvert.fromDecimal(new Long(15), 16));
        logger.info("Decimal to base 16: 53 = " + BaseConvert.fromDecimal(new Long(32), 16));
        
        logger.info("Base 36 to decimal: Z = " + BaseConvert.toDecimal("Z", 36));
        logger.info("Base 36 to decimal: 1Z = " + BaseConvert.toDecimal("1Z", 36));
        logger.info("Base 36 to decimal: A1 = " + BaseConvert.toDecimal("A1", 36));
        logger.info("Base 36 to decimal: Z054C = " + BaseConvert.toDecimal("Z054C", 36));
        logger.info("Decimal to base 36: 58793196 = " + BaseConvert.fromDecimal(new Long(58793196), 36));
        logger.info("Decimal to base 36: 361 = " + BaseConvert.fromDecimal(new Long(361), 36));
        logger.info("Decimal to base 36: 71 = " + BaseConvert.fromDecimal(new Long(71), 36));
        logger.info("Decimal to base 36: 3255428 = " + BaseConvert.fromDecimal(new Long(3255428), 36));
        
    }
    
}
